package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.constant.FinancingTargetConstant;
import com.laicunba.pojo.FinancingTargetBidDO;
import com.laicunba.pojo.FinancingTargetDO;
import com.laicunba.pojo.FuiouPayForReqDO;
import com.laicunba.pojo.TaskDO;
import com.laicunba.pojo.UserBankDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.pojo.WithdrawDO;
import com.laicunba.pojo.WithdrawFinancingTargetBidItemDO;
import com.laicunba.service.FinancingTargetBidService;
import com.laicunba.service.FinancingTargetService;
import com.laicunba.service.TaskService;
import com.laicunba.service.UserBankService;
import com.laicunba.service.UserService;
import com.laicunba.service.WithdrawFinancingTargetBidItemService;
import com.laicunba.service.WithdrawService;
import com.laicunba.service.accounting.NegotiateBuyService;
import com.laicunba.service.fuiou.FuiouPayForReqService;
import com.laicunba.service.profit.SuiCunBaoProfitService;
import com.laicunba.service.profit.SuiCunBaoProfitService.MergedProfitResult;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.BigDecimalUtil;
import com.laicunba.util.DateUtil;
import com.laicunba.util.SessionUtil;
import com.laicunba.util.StringUtil;

@Service
public class WithdrawServiceImpl extends BaseServiceImpl implements WithdrawService {
	private static final Logger LOG = Logger.getLogger(WithdrawServiceImpl.class);
	@Autowired
	private FinancingTargetBidService financingTargetBidService;
	@Autowired
	private SuiCunBaoProfitService suiCunBaoProfitService;

	@Autowired
	private UserService userService;

	@Autowired
	private WithdrawFinancingTargetBidItemService withdrawFinancingTargetBidItemService;

	@Autowired
	private FinancingTargetService financingTargetService;

	@Autowired
	private NegotiateBuyService negotiateBuyService;
	@Autowired
	private FuiouPayForReqService fuiouPayForReqService;
	@Autowired
	private UserBankService userBankService;
	@Autowired
	private TaskService taskService;

	/**
	 * 根据用户输入的金额进行提现 1、扣收益节余字段 2、一个一个扣可提现隋存宝 3、多出来的收益,放回收益节余字段
	 */
	@Transactional
	@Override
	public SCBWithdrawResult doWithDrawApply(SCBWithdrawParam param) {
		// 验证用户是否存在
		UserDO user = userService.get(UserDO.class, param.getUserId());
		AssertUtil.assertNotNull(user, "USER_NOT_EXIST");

		String dangerCode = userService.testDangerous(user.getId());
		AssertUtil.assertTrue(dangerCode == null, dangerCode);

		// 获得可取现金额
		MergedProfitResult profitResult = suiCunBaoProfitService.getMergedProfit(param.getUserId());
		AssertUtil.assertNotNull(profitResult, "CANT_FIND_PROFIT_RESULT");
		BigDecimal totalCanWithdrawAmount = profitResult.getPrincipal();
		if (profitResult.getTotalProfit() != null) {
			totalCanWithdrawAmount = totalCanWithdrawAmount.add(profitResult.getTotalProfit());
		}
		// 断言有足够的可取现金额
		AssertUtil.assertTrue(param.getWithdrawAmount().compareTo(totalCanWithdrawAmount) <= 0, "NOT_HAS_ENOUGH_MONEY");

		// 加载所有可取现标的
		List<FinancingTargetBidDO> bidList = financingTargetBidService.findWithdrawAble(param.getUserId(), "SCB");
		AssertUtil.assertNotNull(bidList);
		SCBWithdrawResult result = new SCBWithdrawResult();
		result.setWithdrawProfit(BigDecimal.ZERO);
		BigDecimal remainAmount = param.getWithdrawAmount();

		// 扣掉前期收益节余
		BigDecimal subtractAmount = BigDecimal.ZERO;
		if (user.getRemainProfit() != null && user.getRemainProfit().compareTo(BigDecimal.ZERO) > 0) {
			if (user.getRemainProfit().compareTo(remainAmount) < 0) {
				subtractAmount = user.getRemainProfit();
			} else if (user.getRemainProfit().compareTo(remainAmount) == 0) {
				subtractAmount = user.getRemainProfit();
			} else if (user.getRemainProfit().compareTo(remainAmount) > 0) {
				subtractAmount = remainAmount;
			}
			remainAmount = remainAmount.subtract(subtractAmount);
			user.setRemainProfit(user.getRemainProfit().subtract(subtractAmount));
			if (!param.isTry()) {
				AssertUtil.assertTrue(userService.subtractRemainProfit(user.getId(), subtractAmount), "SUBTRACT_REMAIN_PROFIT_FAIL");
			}
		}
		// 取现记录
		WithdrawDO withdrawDO = new WithdrawDO();
		if (!param.isTry()) {
			withdrawDO.setApplyTime(new Date());
			withdrawDO.setStatus("apply");
			withdrawDO.setWithdrawPrincipal(param.getWithdrawAmount());
			withdrawDO.setUserId(user.getId());
			withdrawDO.setPid(StringUtil.isNotEmpty(param.getPid()) ? param.getPid() : user.getPid());
			withdrawDO.setName(StringUtil.isNotEmpty(param.getHolder()) ? param.getHolder() : user.getTrueName());
			withdrawDO.setBankCardNo(param.getBankCardNo());
			withdrawDO.setBankName(param.getBankName());
			withdrawDO.setBankNo(param.getBankCode());
			withdrawDO.setType("SCB");
			withdrawDO.setMark(param.getMark());
			withdrawDO.setSubtractRemainProfit(subtractAmount);
			AssertUtil.assertTrue(create(withdrawDO), "CREATE_WITHDRAWDO_ERROR");
		}

		BigDecimal profitNeedAddToUser = BigDecimal.ZERO;
		// 一个一个购买记录扣款
		for (FinancingTargetBidDO bidDO : bidList) {
			if (remainAmount.compareTo(BigDecimal.ZERO) == 0) {
				break;
			}
			BigDecimal canWithdrawAmount = bidDO.getBuyAmount().subtract(bidDO.getWithdrawPrincipal() != null ? bidDO.getWithdrawPrincipal() : BigDecimal.ZERO);
			BigDecimal subtractPrincipal = null;
			BigDecimal subtractProfit = null;
			if (canWithdrawAmount.compareTo(remainAmount) == 0) {
				// 取完
				subtractPrincipal = remainAmount;
				subtractProfit = countProfit(bidDO, new Date());
			} else if (canWithdrawAmount.compareTo(remainAmount) == -1) {
				// 还要再取
				subtractPrincipal = canWithdrawAmount;
				subtractProfit = countProfit(bidDO, new Date());
			} else {
				// 取了一部分
				subtractPrincipal = remainAmount;
				subtractProfit = countProfit(bidDO, new Date());

			}

			profitNeedAddToUser = profitNeedAddToUser.add(subtractProfit);
			remainAmount = remainAmount.subtract(subtractPrincipal);

			BigDecimal diCongProfit = BigDecimal.ZERO;
			// 利息充当取现的一部分
			if (remainAmount.compareTo(BigDecimal.ZERO) > 0) {
				if (profitNeedAddToUser.compareTo(remainAmount) < 0) {
					diCongProfit = profitNeedAddToUser;
				} else if (profitNeedAddToUser.compareTo(remainAmount) == 0) {
					diCongProfit = profitNeedAddToUser;
				} else if (profitNeedAddToUser.compareTo(remainAmount) > 0) {
					diCongProfit = remainAmount;
				}
				remainAmount = remainAmount.subtract(diCongProfit);
				profitNeedAddToUser = profitNeedAddToUser.subtract(diCongProfit);
			}

			if (!param.isTry()) {
				AssertUtil.assertTrue(financingTargetBidService.subtractAmount(bidDO.getId(), subtractPrincipal, subtractProfit), "SUBTRACT_AMOUNT_ERROR");

				WithdrawFinancingTargetBidItemDO itemDO = new WithdrawFinancingTargetBidItemDO();
				itemDO.setFinancingTargetBidId(bidDO.getId());
				itemDO.setWithdrawId(withdrawDO.getId());
				itemDO.setStatus("apply");
				itemDO.setWithdrawPrincipal(subtractPrincipal);
				itemDO.setWithdrawProfit(diCongProfit);
				AssertUtil.assertTrue(withdrawFinancingTargetBidItemService.create(itemDO), "WITHDRAW_FINANCING_TARGET_BID_ITEM_CREATE_ERROR");
			}
		}

		// 获得了足够的金额
		AssertUtil.assertTrue(remainAmount.compareTo(BigDecimal.ZERO) == 0, "REMAIN_AMOUNT_NOT_ZERO");
		if (!param.isTry()) {

			if (profitNeedAddToUser.compareTo(BigDecimal.ZERO) > 0) {
				AssertUtil.assertTrue(userService.addRemainProfit(user.getId(), profitNeedAddToUser), "ADD_REMAIN_PROFIT_FAIL");
			}
		}
		result.setWithdrawId(withdrawDO.getId());
		return result;
	}

	private static final MathContext mc = new MathContext(10, RoundingMode.HALF_DOWN);

	/**
	 * 计算剩余收益<br>
	 * 公式: 剩余本金 * (年化/36500)* (开始计息到当前时间的天数) - 应扣息
	 * 
	 * @param bidDO
	 * @return
	 */

	private BigDecimal countProfit(FinancingTargetBidDO bidDO, Date date) {
		if (date == null) {
			return BigDecimal.ZERO;
		}
		if (bidDO.getWithdrawPrincipal() == null) {
			bidDO.setWithdrawPrincipal(BigDecimal.ZERO);
		}
		if (bidDO.getDeductionProfit() == null) {
			bidDO.setDeductionProfit(BigDecimal.ZERO);
		}
		if (bidDO.getBeginProfit() == null) {
			return BigDecimal.ZERO;
		}

		int days = DateUtil.days(bidDO.getReBeginProfit() != null ? bidDO.getReBeginProfit() : bidDO.getBeginProfit(), date);
		if (days == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal profit = bidDO.getBuyAmount();// .subtract(bidDO.getWithdrawPrincipal());
		if (bidDO.getWithdrawPrincipal() != null) {
			profit = profit.subtract(bidDO.getWithdrawPrincipal());
		}
		profit = profit.multiply(bidDO.getAnnualizedRates().divide(BigDecimal.valueOf(36500), mc));
		profit = profit.multiply(BigDecimal.valueOf(days));
		profit = profit.add(bidDO.getExpireSendProfit()!=null?bidDO.getExpireSendProfit():BigDecimal.ZERO);
		return profit;
	}

	@Override
	public List<Map> findChecking(String type) {
		return queryDao.selectList("WITHDRAW.findChecking", type);
	}

	@Transactional
	public boolean doWithDraw(DoWithdrawParam doWithdrawParam) {
		AssertUtil.assertTrue(updateDao.update("WITHDRAW.change2transfered", doWithdrawParam.getWidthdrawId()) == 1, "CHANGE_2_TRANSFERED_ERROR");
		return true;
	}

	@Transactional
	@Override
	public boolean doWithDraw(CPBDoWithdrawParam cpbWithDraw) {
		FinancingTargetBidDO bidDO = financingTargetBidService.get(FinancingTargetBidDO.class, cpbWithDraw.getFinancingTargetBidId());
		AssertUtil.assertNotNull(bidDO, "BID_NOT_EXIST");
		AssertUtil.assertTrue(bidDO.getWithdrawPrincipal() == null || bidDO.getWithdrawPrincipal().compareTo(BigDecimal.ZERO) == 0, "WITHDRAW_PRINCIPAL_ERROR");
		bidDO.setWithdrawProfit(countProfit(bidDO, bidDO.getEndProfit()));
		bidDO.setWithdrawPrincipal(bidDO.getBuyAmount());
		AssertUtil.assertTrue(financingTargetBidService.updateSkipCheckOwner(bidDO), "UPDATE_BID_ERROR");

		WithdrawDO withdrawDO = new WithdrawDO();
		withdrawDO.setType("CPB");
		withdrawDO.setWithdrawPrincipal(bidDO.getBuyAmount());
		withdrawDO.setWithdrawProfit(bidDO.getWithdrawProfit());
		withdrawDO.setApplyTime(new Date());
		withdrawDO.setStatus("transfered");
		withdrawDO.setUserId(bidDO.getBidUserId());
		withdrawDO.setPid(bidDO.getPayPid());
		withdrawDO.setName(bidDO.getPayName());
		withdrawDO.setBankCardNo(bidDO.getBankCardNo());
		withdrawDO.setBankName(bidDO.getBankName());
		withdrawDO.setBankNo(bidDO.getBankNo());
		withdrawDO.setOptTime(new Date());
		withdrawDO.setSummary(cpbWithDraw.getSummary());
		AssertUtil.assertTrue(create(withdrawDO), "CREATE_ WITHDRAWDO_ERROR");
		if ("ACTIVITY".equalsIgnoreCase(bidDO.getPayMark())) {
			AssertUtil.assertTrue(profit2SuiCunBao(bidDO), "PROFIT_2_SCB_ERROR");
		}
		return true;
	}

	private boolean profit2SuiCunBao(FinancingTargetBidDO bidDO) {
		AssertUtil.assertTrue(bidDO.getWithdrawProfit().compareTo(BigDecimal.ZERO) > 0, "PROFIT_2_SCB_ERROR_PROFIT_IS_TOO_SMALL");
		FinancingTargetDO targetDO = financingTargetService.find(FinancingTargetConstant.TAG_PROFIT_AUTOBUY, bidDO.getWithdrawProfit());
		AssertUtil.assertNotNull(targetDO, "PROFIT_2_SCB_ERROR_CANT_FIND_TARGET");
		AssertUtil.assertTrue("SCB".equalsIgnoreCase(targetDO.getType()), "PROFIT_2_SCB_ERROR_TARGET_NOT_SCB");
		NegotiateBuyService.DoBuyParam param = new NegotiateBuyService.DoBuyParam();
		param.setBuyAmount(bidDO.getWithdrawProfit());
		param.setBuyUserId(bidDO.getBidUserId());
		param.setCertificateId(StringUtil.genGUID());
		param.setSummary(String.format("[%s]收益转随存宝", bidDO.getCertificateId()));
		param.setPayMark("自动购买");
		param.setFinancingTargetId(targetDO.getId());
		AssertUtil.assertNotNull(negotiateBuyService.doBuy(param), "PROFIT_2_SCB_ERROR");
		return true;
	}

	@Override
	public List<WithdrawDO> find(String userId) {
		return queryDao.selectList("WITHDRAW.findByUserId", userId);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Transactional
	@Override
	public boolean doConfirmWithdrawAndSubmitToFuiou(DoWithdrawParam doWithdrawParam) {

		LOG.info(String.format("[rid:%s,tag:WITHDRAW_AND_SUBMIT_TO_FUIOU]WITHDRAW_ID:\t%s", SessionUtil.RID.get(), doWithdrawParam.getWidthdrawId()));
		WithdrawDO withdrawDO = get(WithdrawDO.class, doWithdrawParam.getWidthdrawId());
		AssertUtil.assertNotNull(withdrawDO, "CANT_FIND_WITHDRAWDO");
		AssertUtil.assertTrue("apply".equalsIgnoreCase(withdrawDO.getStatus()), "WITHDRAWDO_NOT_APPLY");
		AssertUtil.assertTrue(StringUtil.isNotEmpty(withdrawDO.getUserId()), "WITHDRAWDO_USER_ID_NOT_EXIST");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		UserBankDO userBankDO = userBankService.find(withdrawDO.getUserId(), withdrawDO.getBankCardNo());
		AssertUtil.assertNotNull(userBankDO, "CANT_FIND_USER_BANK_DO");
		FuiouPayForReqBankVO bankVO = BankListHelper.getFuiouPayForReqBankVO(withdrawDO.getBankNo());
		AssertUtil.assertNotNull(bankVO, "CANT_FIND_FUIOU_PAY_FOR_REQ_BANKVO");
		UserDO userDO = userService.get(UserDO.class, withdrawDO.getUserId());
		AssertUtil.assertNotNull(userDO, "CANT_FIND_USER_DO");
		String dangerCode = userService.testDangerous(userDO.getId());
		AssertUtil.assertTrue(dangerCode == null, dangerCode);

		FuiouPayForReqService.PayForReqParameter param = new FuiouPayForReqService.PayForReqParameter();
		param.setMobile(StringUtil.isNotEmpty(userBankDO.getMobile()) ? userBankDO.getMobile() : userDO.getMobile());
		param.setMerdt(sdf.format(new Date()));
		param.setOrderno(System.currentTimeMillis() + StringUtil.random(4));
		param.setBankno(bankVO.getBankNo());
		param.setCityno("3310");
		param.setBranchnm(bankVO.getBranchnm());
		param.setAccntno(withdrawDO.getBankCardNo());
		param.setAccntnm(withdrawDO.getName());
		param.setMemo(withdrawDO.getId());
		int amt = 0;
		if (withdrawDO.getWithdrawPrincipal() != null) {
			amt += withdrawDO.getWithdrawPrincipal().multiply(BigDecimal.valueOf(100)).intValue();
		}
		if (withdrawDO.getWithdrawProfit() != null) {
			amt += withdrawDO.getWithdrawProfit().multiply(BigDecimal.valueOf(100)).intValue();
		}
		param.setAmt(amt);
		FuiouPayForReqService.PayForReqResponse response = fuiouPayForReqService.req(param);
		AssertUtil.assertNotNull(response, "FUIOU_REQ_ERROR");
		if (!"000000".equals(response.getRet())) {
			LOG.error("FUIOU_RET_ERROR_" + response.getRet() + ",memo:" + response.getMemo());
			AssertUtil.assertFail("FUIOU_RET_" + response.getRet());

		}

		FuiouPayForReqDO fuiouPayForReqDO = new FuiouPayForReqDO();
		fuiouPayForReqDO.setAccntnm(param.getAccntnm());
		fuiouPayForReqDO.setAccntno(param.getAccntno());
		fuiouPayForReqDO.setAmt(param.getAmt());
		fuiouPayForReqDO.setBankno(param.getBankno());
		fuiouPayForReqDO.setBranchnm(param.getBranchnm());
		fuiouPayForReqDO.setEntseq(param.getEntseq());
		fuiouPayForReqDO.setMerdt(param.getMerdt());
		fuiouPayForReqDO.setMobile(param.getMobile());
		fuiouPayForReqDO.setOrderno(param.getOrderno());
		fuiouPayForReqDO.setReqMemo(param.getMemo());
		fuiouPayForReqDO.setRespMemo(response.getMemo());
		fuiouPayForReqDO.setRespRet(response.getRet());
		fuiouPayForReqDO.setMobile(param.getMobile());
		fuiouPayForReqDO.setWithdrawId(withdrawDO.getId());
		fuiouPayForReqDO.setCityno(param.getCityno());
		if (!fuiouPayForReqService.create(fuiouPayForReqDO)) {
			LOG.error("Important Bug[FUIOU_PAY_FOR_REQ_SUCCESS_BUG_LOG_ERROR] :" + fuiouPayForReqDO.toString());
		}
		Map map = new HashMap();
		map.put("id", doWithdrawParam.getWidthdrawId());
		map.put("certificateId", fuiouPayForReqDO.getOrderno());
		AssertUtil.assertTrue(updateDao.update("WITHDRAW.change2send_autosubmit2fuiou", map) == 1, "CHANGE_2_SEND_ERROR");

		// 创建定时任务
		TaskDO taskDO = new TaskDO();
		taskDO.setStatus("new");
		taskDO.setUserId(userDO.getId());
		taskDO.setTimer(new Date());
		taskDO.getTimer().setHours(taskDO.getTimer().getHours() + 4);
		taskDO.setParam(String.format("{\"wid\":\"%s\",\"fprid\":\"%s\"}", withdrawDO.getId(), fuiouPayForReqDO.getId()));
		taskDO.setType("FUIOU_WITHDRAW");
		taskService.create(taskDO);
		return true;
	}

	@Transactional
	@Override
	public WithdrawDO doConfirmWithdrawAndSubmitToFuiou(CPBDoWithdrawParam param) {
		AssertUtil.assertNotNull(param.getFinancingTargetBidId(), "PARAM_BID_ID_NOT_EXIST");
		AssertUtil.assertNotNull(param.getSummary(), "PARAM_SUMMARY_NOT_EXIST");

		FinancingTargetBidDO bidDO = financingTargetBidService.get(FinancingTargetBidDO.class, param.getFinancingTargetBidId());
		AssertUtil.assertNotNull(bidDO, "BID_NOT_EXIST");
		AssertUtil.assertTrue(bidDO.getWithdrawPrincipal() == null || bidDO.getWithdrawPrincipal().compareTo(BigDecimal.ZERO) == 0, "WITHDRAW_PRINCIPAL_ERROR");

		AssertUtil.assertTrue(FinancingTargetConstant.TYPE_FIXED.equalsIgnoreCase(bidDO.getType()), "BID_NOT_FIXED");
		AssertUtil.assertTrue(bidDO.isPay(), "BID_NOT_PAY");
		// 只有通过银行卡支付的
		AssertUtil.assertFalse("ACTIVITY".equalsIgnoreCase(bidDO.getPayMark()), "IS_ACTIVITY_BID");
		AssertUtil.assertFalse("JZH".equalsIgnoreCase(bidDO.getPayMark()), "JZH_BID_CANT_SUBMIT_TO_FUIOU");
		AssertUtil.assertFalse(bidDO.isTransferCurrent(), "IS_TRANSFER_CURRENT");
		bidDO.setWithdrawProfit(countProfit(bidDO, bidDO.getEndProfit()));
		bidDO.setWithdrawPrincipal(bidDO.getBuyAmount());
		UserBankDO userBankDO = null;
		if (StringUtil.isNotEmpty(bidDO.getBankCardNo())) {
			userBankDO = userBankService.find(bidDO.getBidUserId(), bidDO.getBankCardNo());
		} else if (FinancingTargetConstant.isDemand2Fix(bidDO.getPayMark())) {
			userBankDO = userBankService.findRepaymentCard(bidDO.getBidUserId());
		}
		AssertUtil.assertNotNull(userBankDO, "CANT_FIND_USER_BANK_DO");

		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

		FuiouPayForReqBankVO bankVO = BankListHelper.getFuiouPayForReqBankVO(userBankDO.getBankCode());
		AssertUtil.assertNotNull(bankVO, "CANT_FIND_FUIOU_PAY_FOR_REQ_BANKVO");
		UserDO userDO = userService.get(UserDO.class, bidDO.getBidUserId());
		AssertUtil.assertNotNull(userDO, "CANT_FIND_USER_DO");

		/*
		 * 提交富友支付
		 */
		FuiouPayForReqService.PayForReqParameter fuiouParam = new FuiouPayForReqService.PayForReqParameter();
		fuiouParam.setMobile(StringUtil.isNotEmpty(userBankDO.getMobile()) ? userBankDO.getMobile() : userDO.getMobile());
		fuiouParam.setMerdt(sdf.format(new Date()));
		fuiouParam.setOrderno(System.currentTimeMillis() + StringUtil.random(4));
		fuiouParam.setBankno(bankVO.getBankNo());
		fuiouParam.setCityno("3310");
		fuiouParam.setBranchnm(bankVO.getBranchnm());
		fuiouParam.setAccntno(userBankDO.getBankCardNo());
		fuiouParam.setAccntnm(userBankDO.getHolder());
		fuiouParam.setMemo("BID_" + bidDO.getId());
		int amt = bidDO.getWithdrawPrincipal().add(bidDO.getWithdrawProfit()).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)).intValue();

		// if (bidDO.getWithdrawPrincipal() != null) {
		// amt +=
		// bidDO.getWithdrawPrincipal().multiply(BigDecimal.valueOf(100)).intValue();
		// }
		// if (bidDO.getWithdrawProfit() != null) {
		// amt +=
		// bidDO.getWithdrawProfit().multiply(BigDecimal.valueOf(100)).intValue();
		// }
		fuiouParam.setAmt(amt);
		FuiouPayForReqService.PayForReqResponse response = fuiouPayForReqService.req(fuiouParam);
		AssertUtil.assertNotNull(response, "FUIOU_REQ_ERROR");
		if (!"000000".equals(response.getRet())) {
			LOG.error("FUIOU_RET_ERROR_" + response.getRet() + ",memo:" + response.getMemo());
			AssertUtil.assertFail("FUIOU_RET_" + response.getRet());

		}
		/*
		 * 本地取款
		 */
		String summary = DateUtil.format(new Date()) + "进行了富友免复核自动打款,富友order_no:" + fuiouParam.getOrderno();
		bidDO.setSummary(StringUtil.isEmpty(bidDO.getSummary()) ? summary : bidDO.getSummary() + "," + summary);
		AssertUtil.assertTrue(financingTargetBidService.updateSkipCheckOwner(bidDO), "UPDATE_BID_ERROR");
		WithdrawDO withdrawDO = new WithdrawDO();
		withdrawDO.setType("CPB");
		withdrawDO.setWithdrawPrincipal(bidDO.getBuyAmount());
		withdrawDO.setWithdrawProfit(bidDO.getWithdrawProfit());
		withdrawDO.setApplyTime(new Date());
		withdrawDO.setStatus("send");
		withdrawDO.setUserId(bidDO.getBidUserId());
		withdrawDO.setPid(bidDO.getPayPid());
		withdrawDO.setName(bidDO.getPayName());
		withdrawDO.setBankCardNo(bidDO.getBankCardNo());
		withdrawDO.setBankName(bidDO.getBankName());
		withdrawDO.setBankNo(bidDO.getBankNo());
		withdrawDO.setOptTime(new Date());
		withdrawDO.setCertificateId(fuiouParam.getOrderno());
		withdrawDO.setSummary(param.getSummary());
		AssertUtil.assertTrue(create(withdrawDO), "CREATE_WITHDRAWDO_ERROR");
		/*
		 * 记录富友日志
		 */
		FuiouPayForReqDO fuiouPayForReqDO = new FuiouPayForReqDO();
		fuiouPayForReqDO.setAccntnm(fuiouParam.getAccntnm());
		fuiouPayForReqDO.setAccntno(fuiouParam.getAccntno());
		fuiouPayForReqDO.setAmt(fuiouParam.getAmt());
		fuiouPayForReqDO.setBankno(fuiouParam.getBankno());
		fuiouPayForReqDO.setBranchnm(fuiouParam.getBranchnm());
		fuiouPayForReqDO.setEntseq(fuiouParam.getEntseq());
		fuiouPayForReqDO.setMerdt(fuiouParam.getMerdt());
		fuiouPayForReqDO.setMobile(fuiouParam.getMobile());
		fuiouPayForReqDO.setOrderno(fuiouParam.getOrderno());
		fuiouPayForReqDO.setReqMemo(fuiouParam.getMemo());
		fuiouPayForReqDO.setRespMemo(response.getMemo());
		fuiouPayForReqDO.setRespRet(response.getRet());
		fuiouPayForReqDO.setMobile(fuiouParam.getMobile());
		fuiouPayForReqDO.setWithdrawId(withdrawDO.getId());
		fuiouPayForReqDO.setCityno(fuiouParam.getCityno());
		if (!fuiouPayForReqService.create(fuiouPayForReqDO)) {
			LOG.error("Important Bug[FUIOU_PAY_FOR_REQ_SUCCESS_BUG_LOG_ERROR] :" + fuiouPayForReqDO.toString());
		}

		// 创建定时任务
		TaskDO taskDO = new TaskDO();
		taskDO.setStatus("new");
		taskDO.setUserId(userDO.getId());
		taskDO.setTimer(new Date());
		taskDO.getTimer().setHours(taskDO.getTimer().getHours() + 4);
		taskDO.setParam(String.format("{\"wid\":\"%s\",\"fprid\":\"%s\",\"bid\":\"%s\"}", withdrawDO.getId(), fuiouPayForReqDO.getId(), bidDO.getId()));
		taskDO.setType("FUIOU_WITHDRAW");
		taskService.create(taskDO);
		return withdrawDO;
	}

	@Override
	public boolean isTimeWidthdrawApply(Date time) {
		if (time == null) {
			return false;
		}
		if (time.getHours() == 0 || time.getHours() == 1 || time.getHours() == 2) {
			return false;
		}
		return true;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Transactional
	public boolean finish(String withdrawId, String certificateId) {
		Map map = new HashMap();
		map.put("id", withdrawId);
		map.put("certificateId", certificateId);
		AssertUtil.assertTrue(updateDao.update("WITHDRAW.change2transferedFromSend", map) == 1, "CHANGE_2_TRANSFERED_ERROR");
		return true;
	}
	
	@Override
	public BigDecimal countProfit(String withdrawId) {
		return queryDao.selectOne("WITHDRAW.countProfit", withdrawId);
	}
	
	@Override
	public BigDecimal countLastCurrentWithdrawProfit(String uid) {
		return queryDao.selectOne("WITHDRAW.countLastCurrentWithdrawProfit", uid);
	}
	
	@Override
	public List<WithdrawDO> findJzhRedemptionList(String userId, int limit, int offset) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("userId", userId);
		param.put("limit", limit);
		param.put("offset", offset);
		return queryDao.selectList("WITHDRAW.findJzhRedemptionList", param);
	}
}
